package controllers;

import dao.common.OrderManager;
import dao.common.UserManager;
import dao.hibernate.OrderManagerHB;
import dao.hibernate.UserManagerHB;
import models.entities.OrderEntity;
import models.entities.PaginatedList;
import models.entities.ShoppingCartEntity;
import models.exceptions.CreateEntityException;
import models.exceptions.DeleteEntityException;
import models.exceptions.GetEntityException;
import models.exceptions.UpdateEntityException;
import models.helpers.UserHelper;
import models.repository.OrderRepositorySQL;
import models.repository.ShoppingCartRepositorySQL;
import models.repository.common.OrderRepository;
import models.shop.OrderStatus;
import models.shop.User;
import notifiers.Mails;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import play.data.validation.*;
import play.libs.Mail;
import play.mvc.Controller;
import play.mvc.With;

import java.io.IOException;
import java.util.List;

@With(Secure.class)
public class Order extends Controller {
    @Deprecated
    private static OrderRepository repository = new OrderRepositorySQL();
    private static OrderManager orderManager = new OrderManagerHB();
    public static void summary() throws CreateEntityException, GetEntityException, IOException {
        User user = UserHelper.getUser(session);
        ShoppingCartEntity sCart = new ShoppingCartRepositorySQL().getShoppingCart(user.id);
        if (sCart.items.size() == 0) {
            ShoppingCart.display();
        }
        if (!Validation.hasErrors()) {
            flash.put("userName", user.userInfo.name);
            flash.put("phoneNumber", user.userInfo.phoneNumber);
            flash.put("address", user.userInfo.address);
        }

        render(sCart);
    }

    //TODO: Code readability - Replace parameters with model
    public static void place(
            @Required @MinSize(value = 2, message = "validation.min.userName") @MaxSize(value = 30, message = "validation.max.userName") String userName,
            @Required @Match(value = "^((8|\\+7)[\\- ]?)?(\\(?\\d{3}\\)?[\\- ]?)?[\\d\\- ]{7,10}$", message = "validation.match.phoneNumber") String phoneNumber,
            @Required @MinSize(value = 10, message = "validation.min.address") @MaxSize(value = 100, message = "validation.max.address") String address) throws CreateEntityException, GetEntityException, UpdateEntityException, IOException {
        User user = UserHelper.getUser(session);
        ShoppingCartEntity sCart = new ShoppingCartRepositorySQL().getShoppingCart(user.id);
        if (sCart.items.size() == 0) {
            //TODO: Show message that order repost impossible
            ShoppingCart.display();
        }
        if (Validation.hasErrors()) {
            params.flash();
            Validation.keep();
            summary();
            return;
        }
        user.userInfo.address = address;
        user.userInfo.name = userName;
        user.userInfo.phoneNumber = phoneNumber;
        UserManager userRepository = new UserManagerHB();
        userRepository.updateProfile(user);
        int orderId = repository.place(user.id);
        List<User> admins = userRepository.getAdmins();
        Mails.confirmOrderForAdmin(orderId, user.userInfo, admins);
        confirmation(orderId);
    }

    public static void confirmation(int orderId) throws CreateEntityException, GetEntityException {
        render();
    }

    public static void status(int orderId) {

    }

    @Check("admin")
    public static void list(int pageNumber, int pageSize) throws GetEntityException, IOException {
        PaginatedList<OrderEntity> orderList = repository.getOrderList(pageNumber, pageSize);
        render("Order/list.html", orderList);
    }

    @Check("admin")
    public static void deleteConfirmation(int id){
        render(id);
    }
    @Check("admin")
    public static void delete(int id) throws GetEntityException, DeleteEntityException, IOException {
        orderManager.delete(id);
        list(1, 0);
    }

    @Check("admin")
    public static void getCancelForm(int id){
        models.shop.Order order = orderManager.getById(id);
        render("Order/cancelForm.html", order);
    }

    @Check("admin")
    public static void getConfirmForm(int id){
        models.shop.Order order = orderManager.getById(id);
        render("Order/confirmOrder.html", order);
    }
    @Check("admin")
    public static void postStatus(int orderId, OrderStatus status, String emailBody) throws IOException, GetEntityException, EmailException, CreateEntityException {
        String subject = "";
        User user = UserHelper.getUser(session);
        if (status == OrderStatus.canceled && emailBody != null){
            subject = "Digitalband.ru - Информация о заказе";
            sendEmail(orderId, emailBody, subject, user.userInfo.email);
        } if (status == OrderStatus.confirmed) {
            models.shop.Order order = orderManager.getById(orderId);
            Mails.confirmOrder(orderId, order.userInfo, user.userInfo.email, emailBody);
        }
        orderManager.setStatus(orderId, status);
        display(orderId);
    }

    private static void sendEmail(int orderId, String emailBody, String subject, String from) throws GetEntityException, CreateEntityException, IOException, EmailException {
        models.shop.Order order = orderManager.getById(orderId);
        SimpleEmail email = new SimpleEmail();
        email.setCharset("UTF-8");
        email.setFrom(from);
        email.addTo(order.userInfo.email);
        email.addCc(from);
        email.setSubject(subject);
        email.setMsg(emailBody);
        Mail.send(email);
    }

    @Check("admin")
    public static void listUnconfirmed(){
        List<models.shop.Order> orderList = orderManager.getUnconfirmed();
        render(orderList);
    }

    @Check("admin")
    public static void display(int id) throws GetEntityException, IOException {
        models.shop.Order order = orderManager.getById(id);
        render("Order/display.html", order);
    }
}
